/*
 * IBMPhotoPhun.c
 * 
 * Author: Frank Ableson
 * Contact Info: fableson@navitend.com
 */

#include <jni.h>
#include <android/log.h>
#include <android/bitmap.h>
#include "warper.h"

#define  LOG_TAG    "photowarp"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

typedef struct {
	uint8_t red;
	uint8_t green;
	uint8_t blue;
	uint8_t alpha;
} argb;

/*
 convertToGray
 Pixel operation
 */

JNIEXPORT jint JNICALL Java_kaang_dev_warpimage_NativeBridge_testBitmap(JNIEnv * env, jobject obj, jobject bitmapcolor,jobject bitmapgray)
{
    AndroidBitmapInfo  infocolor;
    void*              pixelscolor; 
    AndroidBitmapInfo  infogray;
    void*              pixelsgray;
    int                ret;
    int 			y;
    int             x;
     
    LOGI("convertToGray");
	if ((ret = AndroidBitmap_getInfo(env, bitmapcolor, &infocolor)) < 0) {
			LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
			return 5;
    }
    
    if ((ret = AndroidBitmap_getInfo(env, bitmapgray, &infogray)) < 0) {
        LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
        return 1;
    }
    
    LOGI(
		"color image :: width is %d; height is %d; stride is %d; format is %d;flags is %d", infocolor.width, infocolor.height, infocolor.stride, infocolor.format, infocolor.flags);
	if (infocolor.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
			LOGE("Bitmap format is not RGBA_8888 !");
			return 2;
    }
    
    LOGI(
		"gray image :: width is %d; height is %d; stride is %d; format is %d;flags is %d", infogray.width, infogray.height, infogray.stride, infogray.format, infogray.flags);
	if (infogray.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
			LOGE("Bitmap format is not A_8 !");
			return 3;
    }
    
    if ((ret = AndroidBitmap_lockPixels(env, bitmapcolor, &pixelscolor)) < 0) {
        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    }

    if ((ret = AndroidBitmap_lockPixels(env, bitmapgray, &pixelsgray)) < 0) {
        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    }

    // modify pixels with image processing algorithm
    for (y=0;y<infocolor.height;y++) {
    	argb * line = (argb *) pixelscolor;
    	argb * grayline = (argb *) pixelsgray;
    	for (x=0;x<infocolor.width;x++) {
    		uint8_t v = 0.3 * line[x].red + 0.59 * line[x].green + 0.11*line[x].blue;
    		grayline[x].red = v;
    		grayline[x].green = v;
    		grayline[x].blue = v;
    		grayline[x].alpha = line[x].alpha;
    	}
    	
    	pixelscolor = (char *)pixelscolor + infocolor.stride;
    	pixelsgray = (char *) pixelsgray + infogray.stride;
    }
    
    LOGI("unlocking pixels");
	AndroidBitmap_unlockPixels(env, bitmapcolor);
	AndroidBitmap_unlockPixels(env, bitmapgray);

	return 4;
}

JNIEXPORT jint JNICALL Java_kaang_dev_warpimage_NativeBridge_applyWarp(JNIEnv* env, jobject obj, jobject originbmp,
		jobject bitmapIn,jint action,jint width,jint blur,jfloat xStart,jfloat yStart,jfloat xEnd,jfloat yEnd)
{
	jint x = (jint)xStart;
	int rs = 0;
	int smooth = 0;
	switch (action)
	{
		case 3:
			rs = Warper_Swirl(env, obj, bitmapIn, (jint)xStart, (jint)yStart, width, blur,1, smooth);
			break;
		case 4:
			rs = Warper_Swirl(env, obj, bitmapIn, (jint)xStart, (jint)yStart, width, blur,-1, smooth);
			break;
		case 2:
			rs = Warper_SphereIn(env, obj, bitmapIn, (jint)xStart, (jint)yStart, width, blur, smooth);
			break;
		case 1:
			rs = Warper_SphereOut(env, obj, bitmapIn, (jint)xStart, (jint)yStart, width, blur, smooth);
			break;
		case 5:
			rs = Warper_Move(env, obj, bitmapIn, (jint)xStart, (jint)yStart, width, blur, xEnd, yEnd, smooth);
			break;
		case 0:
			rs = Warper_Undo(env, obj, originbmp, bitmapIn, (jint)xStart, (jint)yStart, width, blur);
			break;
		default:
			break;
	};

	return rs;
}

JNIEXPORT jstring JNICALL Java_kaang_dev_warpimage_NativeBridge_setOriginalBitmap(JNIEnv * env, jobject obj, jobject bitmapcolor)
{
	AndroidBitmapInfo  infocolor;
	AndroidBitmap_getInfo(env, bitmapcolor, &infocolor);
	LOGI("height is %d",infocolor.height);
	return (*env)->NewStringUTF(env, "Hello from native code!");
}
JNIEXPORT jint JNICALL Java_kaang_dev_warpimage_NativeBridge_WarpCreateSwirlMattix(JNIEnv * env, jobject obj, jfloatArray matrixX, jfloatArray matrixY, jint area, jint w, jint h, jint intensity, jint direction)
{
	return Warper_Create_Swirl_Matrix(env, obj, matrixX, matrixY, area, w, h, intensity, direction);
}
JNIEXPORT jint JNICALL Java_kaang_dev_warpimage_NativeBridge_WarpCreateSphereInMattix(JNIEnv * env, jobject obj, jfloatArray matrixX, jfloatArray matrixY, jint area, jint w, jint h, jint intensity)
{
	return Warper_Create_SphereIn_Matrix(env, obj, matrixX, matrixY, area, w, h, intensity);
}
JNIEXPORT jint JNICALL Java_kaang_dev_warpimage_NativeBridge_WarpCreateSphereOutMattix(JNIEnv * env, jobject obj, jfloatArray matrixX, jfloatArray matrixY, jint area, jint w, jint h, jint intensity)
{
	return Warper_Create_SphereOut_Matrix(env, obj, matrixX, matrixY, area, w, h, intensity);
}
JNIEXPORT jint JNICALL Java_kaang_dev_warpimage_NativeBridge_applyWarp1(JNIEnv* env, jobject obj, jobject originbmp,
		jobject bitmapIn,jint action, jfloatArray matrixX, jfloatArray matrixY, jint width,jint blur,jfloat xStart,jfloat yStart,jfloat xEnd,jfloat yEnd)
{
	int rs = 0;
	int smooth = 1;
	switch (action)
	{
		case 4:
			rs = Warper_Move(env, obj, bitmapIn, (jint)xStart, (jint)yStart, width, blur, xEnd, yEnd, smooth);
			break;
		case 5:
			rs = Warper_Undo(env, obj, originbmp, bitmapIn, (jint)xStart, (jint)yStart, width, blur);
			break;
		default:
			rs = Warper_Transform(env, obj, bitmapIn, matrixX, matrixY, xStart, yStart, width, blur, smooth);
			break;
	};
	return rs;
}
